package com.bwie.service.impl;

import cn.hutool.core.util.IdUtil;
import com.bwie.common.constants.Constants;
import com.bwie.common.constants.JwtConstants;
import com.bwie.common.constants.TokenConstants;
import com.bwie.common.domain.User;
import com.bwie.common.exceptions.BizExceptions;
import com.bwie.common.result.Result;
import com.bwie.common.utils.JwtUtils;
import com.bwie.remote.UserRemote;
import com.bwie.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @className: UserServiceImpl
 * @Description: TODO
 * @version: v1.８.0
 * @author: 汪菲阳
 * @date: 2025/11/10 10:05
 */
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserRemote userRemote;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    /**
     * 用户锁
     */
    private static final String USER_LOCK_KEY="user:lock";
    /**
     * 最大错误次数
     */
    private static final Integer FAIL_NUM=5;
    /**
     * 错误次数前缀
     */
    private static final String FAIL_NUM_INCR="fail:num:incr";


    @Override
    public String login(User user) {
        //卫语句
        String userName = user.getUserName();
        String userPassword = user.getUserPassword();
        //判断锁是否已存在
        if (redisTemplate.hasKey(USER_LOCK_KEY+userName)){
            throw new BizExceptions(Constants.USER_LOCK_EXITS_CODE,Constants.USER_LOCK_EXITS_MSG);
        }
        //远程调用--根据用户名称查询用户信息
        Result<User> userResult = userRemote.selectUserByUserName(userName);
        //熔断
        if (userResult.getCode()== Constants.ERROR){
            throw new BizExceptions(Constants.LOGIN_SELECT_ERROR_CODE,Constants.LOGIN_SELECT_ERROR_MSG);
        }
        //获取响应信息
        User loginData = userResult.getData();
        //非空
        if (loginData == null){
            throw new BizExceptions(Constants.LOGIN_USER_NOT_EXIST_CODE,Constants.LOGIN_USER_NOT_EXIST_MSG);
        }
        //获取查询到的密码
        String dbPassword = loginData.getUserPassword();
        //判断密码是否正确
        if (!userPassword.equals(dbPassword)){
            //自增错误次数
            Long failCount = redisTemplate.opsForValue().increment(FAIL_NUM_INCR + userName);
            //设置锁定时间
            redisTemplate.expire(USER_LOCK_KEY+userName,1, TimeUnit.DAYS);
            //判断错误次数是否大于最大错误次数
            if (failCount>FAIL_NUM){
                //如果大于则存入锁
                redisTemplate.opsForValue().set(USER_LOCK_KEY+userName,true);
                //设置锁定时间
                redisTemplate.expire(USER_LOCK_KEY+userName,1, TimeUnit.DAYS);

                //清除过期时间
                redisTemplate.delete(FAIL_NUM+userName);
            }
            throw new BizExceptions(Constants.LOGIN_PWD_ERROR_CODE,Constants.LOGIN_PWD_ERROR_MSG);
        }
        //登录成功则清除锁
        redisTemplate.delete(USER_LOCK_KEY+userName);
        //生成token
        Map<String, Object> map = new HashMap<>();
        String userKey = IdUtil.fastSimpleUUID();
        map.put(JwtConstants.USER_KEY,userKey);
        String token = JwtUtils.createToken(map);
        //存入redis
        redisTemplate.opsForValue().set(TokenConstants.LOGIN_TOKEN_KEY+userKey,loginData,30,TimeUnit.MINUTES);
        return token;
    }
}
